class PlayerControllerSystem extends System {
	constructor(world) {
		super(world);
        this._keys = {};
        this._gameOver = false;

        this.getWorld().getMessageManager().subscribe('GAME_OVER', () => this.onGameOver());
        document.onkeydown = (...params) => this.onKeyDown(...params);
        document.onkeyup = (...params) => this.onKeyUp(...params);
	}

    onKeyDown(event) {
        this._keys[event.key] = true;
    }

    onKeyUp(event) {
        this._keys[event.key] = false;
    }

    isKeyDown(key) {
        return this._keys[key];
    }

    getHorizontalMovement(scalar) {
        return (this.isKeyDown('d') || this.isKeyDown('ArrowRight') ? scalar : 0) + (this.isKeyDown('a') || this.isKeyDown('ArrowLeft') ? -scalar : 0);
    }

    getVerticalMovement(scalar) {
        return (this.isKeyDown('s') || this.isKeyDown('ArrowDown') ? scalar : 0) + (this.isKeyDown('w') || this.isKeyDown('ArrowUp') ? -scalar : 0);
    }

	execute() {
        if (this._gameOver === false) {
            const {width, height, ballRadius: radius} = config;
            for (const entity of this.getWorld().getEntities()) {
                const playerControllerComponent = entity.getComponent(PlayerControllerComponent);
                const positionComponent = entity.getComponent(PositionComponent);
                if (playerControllerComponent && positionComponent) {
                    const scalar = playerControllerComponent.speed * time.delta;
                    positionComponent.x = Math.max(0 + radius, Math.min(positionComponent.x + this.getHorizontalMovement(scalar), width - radius));
                    positionComponent.y = Math.max(0 + radius, Math.min(positionComponent.y + this.getVerticalMovement(scalar), height - radius));
                }
            }
        }
	}

	onGameOver() {
	    this._gameOver = true;
    }
}